#!/usr/bin/env python
#
# Copyright 2008 Richard J. Bell. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

""" User classes for GeoWiki. """
# Python Imports
from django.utils import simplejson as json
import urllib
import logging
from operator import itemgetter

# Google App Engine Imports
from google.appengine.ext import db
from google.appengine.api import users

# Application Imports
from app.gwbaserequesthandler import GWRequestHandler

class GWUser(db.Model):
    """ GWUser object. 
        Note, it is necessary to pass GWuser references to various HTML pages.
        This is accomplished by using str(gwuser.key()), that is we pass the 
        ascii representation of the GWUser key.  We can get back to the GWUser
        via Key(encode=gwuser.key()).
        
        Design note: GWUser does not have a description as that is properly 
        handled with a GeoWiki page.
    """
    user = db.UserProperty()                                                    # the user as known by google accounts
    joined = db.DateTimeProperty( auto_now_add=True )                           # datetime user joined
    picture = db.BlobProperty()                                                 # user's picture
    feed = db.StringProperty( default = '')                                     # uri of user's feed
    admin = db.BooleanProperty( default = False )                               # if true, user has application admin priviledges
    show = db.BooleanProperty( default = False )                                # if true, show user in user list
    blacklist = db.BooleanProperty( default = False )                           # if true, user is blacklisted and cannot login
    lastlogin = db.DateTimeProperty( auto_now = True )                          # time of user's last login
    
    def keyStr( self ):
        """ Return the GWUser key as a string """
        return str( self.key() )
    def nickname( self ):
        """ Return an appropriate nickname for this user """
        return self.user.nickname()
    @staticmethod
    def isAdmin( ):
        """ Get current user and wiki user if any.
        Parameters: none
        Returns: 
          isAdmin, boolean - True if user has GeoWiki admin rights
        """
        user = users.get_current_user()
        if not user: return False
        gwuser = GWUser.gql('WHERE user = :1', user).get()
        if not gwuser: return False
        return gwuser.admin

    @staticmethod
    def isLogin( ):
        """ Get current user and wiki user if any.
        Parameters: none
        Returns: 
          isLogin, boolean - True if user has GeoWiki admin rights
        """
        user = users.get_current_user()
        if not user: return False
        gwuser = GWUser.gql('WHERE user = :1', user).get()
        if gwuser == None: return False
        return True
    @staticmethod
    def getUserInfo():
        """ Get current user and wiki user if any.
        Parameters: none
        Returns: 
          currentUser, user - the currently loged in app server user
          wikiUser, GWUser - the corresponding wikiUser object
        """
        user = users.get_current_user()
        if user == None:
            return (None, None)
        gwuser = GWUser.gql('WHERE user = :1', user).get()
        return (user, gwuser)
    @staticmethod
    def get():
        ( user, gwuser ) = GWUser.getUserInfo()
        return gwuser
    @staticmethod
    def isDeveloper():
        return users.is_current_user_admin()
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# User login/logout support
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
class UserLogin(GWRequestHandler):
    """ Display user login dialog """
    def get(self):
        #logging.info('===== in UserLogin, about to users.create_login_url')
        link = self.request.get('link')
        logging.debug('link is <<%s>>' % link )
        if link == '': link = '/Great_Loop_Home'
        self.redirect(users.create_login_url('/gw/login2?link=' + link));
        
class UserLogin2(GWRequestHandler):
    """ Phase 2 of user login processing.  Updates the last login time. """
    def get(self):
        """ Update the last login time. """
        #logging.info('===== in UserLogin2')
        # make sure user is loged in
        usr = users.get_current_user()
        logging.debug('got user %s' % usr)
        if usr == None:
            self.generate( 'admin/loginrequired.html', templateValues={ 'title': 'Login Required' } )
            return
        # update last login time
        logging.debug('getUserInfo')
        usr, wusr = GWUser.getUserInfo()
        if wusr == None:
            # create this user
            logging.debug('create user GWUser')
            wusr = GWUser( user = usr, nickname = usr.nickname() )
        wusr.put()
        link = self.request.get('link')
        if link == '': link = '/Great_Loop_Home'
        self.redirect( link )

class UserLogout(GWRequestHandler):
    """ Display user logout dialog. """
    def get(self):
        """ Display user logout dialog. """
        # add code here to track login time by user
        self.redirect(users.create_logout_url('/Great_Loop_Home'));
        
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# Admin users page support
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
class UsersEdit(GWRequestHandler):
    """ Handle admin requests """
    def get(self):
        if GWUser.isAdmin():
            self.generate('admin/users.html', templateValues={ 'title': 'User Edit' })
        else:
            self.generate('admin/adminrequired.html', templateValues={ 'title': 'Admin Required' })
        return
        
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# User list support
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
class UsersList(GWRequestHandler):
    """ Return json object with list of users. """
    def get(self):
        """ Return json object with list of users. """
        userlist = []
        gwusers = GWUser.all()
        for gwuser in gwusers:
            userlist.append( {'userkey': str(gwuser.key()),                     # on pages we work with GWuser key
                              'nickname': gwuser.user.nickname(),
                              'joined': gwuser.joined.strftime('%Y-%m-%d %H:%M'),
                              #'picture': gwuser.picture, 
                              'feed': gwuser.feed,
                              'lastlogin': gwuser.lastlogin.strftime('%Y-%m-%d %H:%M'),
                              'admin': gwuser.admin, 
                              'show': gwuser.show,
                              'blacklist': gwuser.blacklist
                              })
        userlist.sort( key = itemgetter('nickname') )                           # sort by nickname
        jsonObj = {'users': userlist }                                          # make json object
        jsonmsg = json.dumps(jsonObj)
        # return it
        self.response.headers['Content-Type'] = 'application/javascript'
        self.response.out.write(jsonmsg)

#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# User list support
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
class Users(GWRequestHandler):        
    def delete(self, userkey):
        """ handle json/user/user delete request """
        if not GWUser.isAdmin:
            self.generate( 'admin/adminrequired.html', templateValues={ 'title': 'Admin Required' } )
            return
        gwuser = db.get( db.Key( userkey ))
        if not gwuser:
            # no such user
            self.error( 404 )
            return
        nn = gwuser.user.nickname()
        gwuser.delete()
        # Return success
        # Here return type application/javascript since browsers will display it 
        # as an aid to debug.  Application/json is generally not displayed.
        self.response.headers['Content-Type'] = 'application/javascript'
        self.response.set_status( 200, "Success deleting user" )
        return
    def get(self, userkey):
        """ handle json/user/user get request """
        gwuser = db.get( db.Key( userkey ))
        if not gwuser:
            # no such user
            self.error( 404 )
            return
        # return the user as a json object
        # turn into a JSON object
        jsonuser = {'userkey': str(gwuser.key()),                               # on pages we work with GWuser key
                    'nickname': gwuser.user.nickname(),
                    'joined': gwuser.joined.strftime('%Y-%m-%d %H:%M'),
                    'picture': gwuser.picture, 
                    'feed': gwuser.feed,
                    'lastlogin': gwuser.lastlogin.strftime('%Y-%m-%d %H:%M'),
                    'admin': gwuser.admin, 
                    'show': gwuser.show,
                    'blacklist': gwuser.blacklist
                    }
        jsonObj = {'user': jsonuser }
        jsonmsg = json.dumps(jsonObj)
        # return it
        self.response.headers['Content-Type'] = 'application/javascript'
        self.response.out.write(jsonmsg)
        return
    def post(self, userkey):
        """ handle json/user/user post request """
        if not GWUser.isAdmin:
            self.generate( 'admin/adminrequired.html', templateValues={ 'title': 'Admin Required' } )
            return
        gwuser = db.get( db.Key( userkey ))
        if not gwuser:
            # no such user
            self.error( 404 )
            return
        img = self.request.get("img")
        if img <> '':
            gwuser.picture = db.Blob( img )
        gwuser.feed = self.request.get("feed")
        gwuser.admin = (self.request.get("admin")=='true')
        gwuser.show = (self.request.get("show")=='true')
        gwuser.blacklist = (self.request.get("blacklist")=='true')
        gwuser.put()
        # Return success
        jsonObj = {'success': True, 'userkey': userkey }
        jsonmsg = json.dumps(jsonObj)
        # Send the response as text/plain since otherwise the browser may
        # decide it's a file download (IE does on anything/JSON or /javascript
        self.response.headers['Content-Type'] = 'text/plain'
        self.response.out.write(jsonmsg)
        return
        